//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <bsp.h>
#include <mmu.h>
#include <init.h>

//const uint_t c_uMaxNumberOfModules  = 16;

typedef struct Package {
    uint32_t        uReserved;
    BootModule      *modules;
    uint_t          uNumberOfModules;
    size_t          uPackageSize;
    char            *szCommandLine;
} Package;

DECL_LINKERSYMBOL byte_t _ImageBegin;
DECL_LINKERSYMBOL byte_t _HeaderBegin;

STATIC DECL_CODEINIT void GetBootModulesFromPackage(
        Package *pPackage, offset_t imageOffset);

EXTERN_C DECL_CODEINIT void CDECL InitBootModules()
{
#if defined(_GNUC)
    // TODO(mips): read from bootmodule
    offset_t imageOffset = (offset_t)0x800ff000;
#elif defined(_EVC)
    offset_t imageOffset = 0x80100000;
#else
#error unknown compiler
#endif

    offset_t packageOffset = *(offset_t *)(8 + imageOffset);

    Package *pPackage = (Package *)(packageOffset + imageOffset);

    if (NULL != pPackage->szCommandLine) {
        bsp.szBootCommandLine =
            (char *)((offset_t)pPackage->szCommandLine + imageOffset);
    }

    GetBootModulesFromPackage(pPackage, imageOffset);
}

STATIC DECL_CODEINIT void GetBootModulesFromPackage(
        Package *pPackage, offset_t imageOffset)
{
    bsp.uNumberOfBootModules = pPackage->uNumberOfModules;

//    assert(c_uMaxNumberOfModules >= bsp.uNumberOfBootModules);

    bsp.pBootModules = (BootModule *)((offset_t)pPackage->modules + imageOffset);

    bsp.regionOfBootModules.uBasePageNo   = VIRTADDR_TO_PAGENO(imageOffset);
    bsp.regionOfBootModules.uLimitPageNo  = bsp.regionOfBootModules.uBasePageNo
        + NUMBEROF_PAGES(RoundUp2(pPackage->uPackageSize, PAGE_SIZE));

#ifdef _DEBUG
    kprintf("Name\t\tBase\t\tLimit\n");
#endif

    for (uint_t i = 0; i < bsp.uNumberOfBootModules; i++) {
        bsp.pBootModules[i].region.uBasePageNo  +=
            VIRTADDR_TO_PAGENO(imageOffset);

        bsp.pBootModules[i].region.uLimitPageNo +=
            VIRTADDR_TO_PAGENO(imageOffset);

#ifdef _DEBUG
        kprintf("%s\t0x%08x\t0x%08x\n",
            bsp.pBootModules[i].szName,
            bsp.pBootModules[i].region.uBasePageNo,bsp.pBootModules[i].region.uLimitPageNo);
#endif
    }
}

